﻿#include "seriportcommunication.h"

//串口通讯构造函数
SeriPortCommunication::SeriPortCommunication(CommunicationProtocol protocal, serialportParameters portPara)
    : PLC_Interface_Base(CommunicationType::SeriPort, protocal),
      parameters(portPara)
{
    //初始化端口
    serialPort = NULL;
    serialPort = new QSerialPort;

    //串口断开时触发串口关闭函数
    connect(serialPort,static_cast<void(QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error),[=](){
        DisConnect();
    });
}

//串口通讯连接函数
bool SeriPortCommunication::Connect()
{
    //设置串口号
    serialPort->setPortName(parameters.portNumber);

    //如果打开失败则返回false
    if(!serialPort->open(QIODevice::ReadWrite))
    {
        serialPortStatus = false;
        emit connectionChangedSignal(serialPortStatus);

        return false;
    }

    //如果打开成功，则设置波特率、数据位、停止位、校验位
    //波特率
    serialPort->setBaudRate(parameters.baudRate);

    //数据位
    serialPort->setDataBits(parameters.dataBits);

    //停止位
    serialPort->setStopBits(parameters.stopBits);

    //校验位
    serialPort->setParity(parameters.parity);

    //流控制
    serialPort->setFlowControl(QSerialPort::NoFlowControl);

    //设置串口状态标志为打开
    serialPortStatus = true;
    emit connectionChangedSignal(serialPortStatus);

    return true;
}

//串口关闭函数
void SeriPortCommunication::DisConnect()
{
    //设置串口状态标志为关闭
    serialPortStatus = false;
    emit connectionChangedSignal(serialPortStatus);

    //关闭串口、清除串口
    serialPort->clear();
    serialPort->close();

    //清空请求报文数组
    ReceiveMessage.clear();
}

//报文发送函数
int SeriPortCommunication::MessageSend(const QByteArray &arr)
{
    if(serialPortStatus)
    {
        serialPort->write(arr);
        serialportSendIdentifier = true;

        emit requestMessageSendOverSignal();
    }
    else
    {
        serialportSendIdentifier = false;

        emit connectionChangedSignal(false);
        return 0;
    }

    for(resendNumber = 0; resendNumber < RESENDNUMBER; resendNumber++)
    {
        if(serialPort->waitForReadyRead(WAITE_FOR_RESPONSE))
        {
            return 1;
        }

        //使用TCP向目标从站重新传输请求报文
        serialPort->write(RequestMessage);
        serialportSendIdentifier = true;

        emit requestMessageSendOverSignal();
    }

    //重传次数费完
    emit resendMessageFail();

    //清空请求报文数组
    RequestMessage.clear();
    serialportSendIdentifier = false;

    return 0;
}

//报文接收函数
bool SeriPortCommunication::MessageReceive(QByteArray &arr)
{
    if(serialPortStatus)
    {
        arr = serialPort->readAll();
        serialportSendIdentifier = false;

        emit receivedAMessageSignal();

        return true;
    }

    emit connectionChangedSignal(serialPortStatus);
    return false;
}
